﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using XLua;
using Action = System.Action;
using System.IO;

[LuaCallCSharp]
public class LuaScriptBehavior: MonoBehaviour
{
    [System.Serializable]
    public class ScriptValue
    {
        public string name;
        public GameObject value;
    }

    [SerializeField]
    private string scriptName = "";
    [SerializeField]
    private ScriptValue[] mValue;
    
    private Action luaStart;
    private Action luaUpdate;
    private Action luaOnDestroy;

    private LuaTable scriptObj;
    void _Awake()
    {
        scriptObj = XluaEngine.Lua.NewTable();

        LuaTable meta = XluaEngine.Lua.NewTable();
        meta.Set("__index", XluaEngine.Lua.Global);
        scriptObj.SetMetaTable(meta);
        meta.Dispose();

        scriptObj.Set("self", this);
        foreach (var injection in mValue)
        {
            scriptObj.Set(injection.name, injection.value);
        }
        byte[] bytes = LoadFromCustomLoaders(scriptName);
        if (bytes == null)
            bytes = LoadFromResources(scriptName);
        if (bytes == null)
            bytes = LoadFromStreamingAssetsPath(scriptName);
        if (bytes != null)
        {
            XluaEngine.Lua.DoString(bytes, scriptName, scriptObj);

            scriptObj.Get("Start", out luaStart);
            scriptObj.Get("Update", out luaUpdate);
            scriptObj.Get("OnDestroy", out luaOnDestroy);

            Action luaAwake = scriptObj.Get<Action>("Awake");
            if (luaAwake != null)
            {
                luaAwake();
            }
        }
    }
    // Use this for initialization
    void Start()
    {
        _Awake();
        if (luaStart != null)
        {
            luaStart();
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (luaUpdate != null)
        {
            luaUpdate();
        }
    }

    void OnDestroy()
    {
        if (luaOnDestroy != null)
        {
            luaOnDestroy();
        }
        luaOnDestroy = null;
        luaUpdate = null;
        luaStart = null;
        scriptObj.Dispose();
        mValue = null;
    }
#region Load File Func
    static byte[] LoadFromResources(string luaFile)
    {
        if (luaFile.EndsWith(".lua"))
            luaFile = luaFile.Substring(0, luaFile.LastIndexOf('.'));
        string filename = luaFile.Replace('.', '/') + ".lua";
        // Load with Unity3D resources 
        UnityEngine.TextAsset file = (UnityEngine.TextAsset)UnityEngine.Resources.Load(filename);
        if (file == null)
        {
            return null;
        }
        else
        {
            return file.bytes;
        }
    }
    static byte[] LoadFromStreamingAssetsPath(string luaFile)
    {
        try
        {
            if (luaFile.EndsWith(".lua"))
                luaFile = luaFile.Substring(0, luaFile.LastIndexOf('.'));
            luaFile = luaFile.Replace('.', '/') + ".lua";
            var filepath = UnityEngine.Application.streamingAssetsPath + "/" + luaFile;
#if UNITY_EDITOR
            if (File.Exists(filepath))
            {
                var bytes = File.ReadAllBytes(filepath);
                if (bytes != null)
                    return bytes;
            }
#elif UNITY_ANDROID || UNITY_IPHONE
                UnityEngine.WWW www = new UnityEngine.WWW(filepath);
                while (true)
                {
                    if (www.isDone || !string.IsNullOrEmpty(www.error))
                    {
                        System.Threading.Thread.Sleep(50); //�Ƚ�hacker������
                        if (!string.IsNullOrEmpty(www.error))
                        {
                            return null;
                        }
                        else
                        {
                            return www.bytes;
                        }
                        break;
                    }
                }
#endif
        }
        catch (System.Exception e)
        {
            Debug.LogError("c# exception in LoadFromStreamingAssetsPath:" + e);
        }
        return null;
    } 
     
    static byte[] LoadFromCustomLoaders(string filename)
    {
        try
        {
            foreach (var loader in XluaEngine.Lua.customLoaders)
            {
                string real_file_path = filename;
                byte[] bytes = loader(ref real_file_path);
                if (bytes != null)
                {
                    return bytes;
                }
            }
        }
        catch (System.Exception e)
        {
            Debug.LogError("c# exception in LoadFromCustomLoaders:" + e);
        }
        return null;
    }
#endregion
}
